/**
 * Created by BlueCat on 2020/11/20 10:53.
 **/
import axios from 'axios'
import { Notify } from 'vant'
import { getRealHref, stringify } from './index'
import Share from '@/utils/share'

export const BASE_URL = process.env.VUE_APP_API
export const HEADERS = {
  'X-Requested-With': 'XMLHttpRequest',
  'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
  Version: process.env.VUE_APP_VERSION
}

const CODE_MESSAGE = {
  200: '服务器成功返回请求的数据。',
  201: '新建或修改数据成功。',
  202: '一个请求已经进入后台排队（异步任务）。',
  204: '删除数据成功。',
  400: '发出的请求有错误，服务器没有进行操作。',
  401: '用户没有权限（令牌、用户名、密码错误）。',
  403: '用户得到授权，但是访问是被禁止的。',
  404: '请求不存在，服务器没有进行操作。',
  406: '请求的格式不可得。',
  410: '请求的资源被永久删除，且不会再得到的。',
  422: '当创建一个对象时，发生一个验证错误。',
  500: '服务器发生错误，请检查服务器。',
  502: '网关错误。',
  503: '服务不可用，服务器暂时过载或维护。',
  504: '网关超时。'
}

// 创建一个错误
function createError (msg) {
  const error = new Error(msg)
  console.log(error)
  // this.$toast(error.message)
  error.message && Notify({ message: error.message, color: 'white', background: '#888888' })
  // error.message && Notify(error.message)
  throw error
}

const Request = axios.create({
  baseURL: BASE_URL,
  timeout: 1000 * 10
})

const pending = []
const CancelToken = axios.CancelToken
let arr = [] // 区分是请求还是响应的头部

const removePending = (config, f) => {
  arr = config.url.split(BASE_URL)
  arr = arr[arr.length - 1]
  // 每次请求存储在请求中队列的元素关键值,例如：一个地址为books/create的post请求处理之后为："books/create&post"
  const flagUrl = arr + '&' + config.method
  // 当前请求存在队列中，取消第二次请求
  if (pending.indexOf(flagUrl) !== -1) {
    if (f) {
      // f为实例化的cancelToken函数
      f()
    } else {
      pending.splice(pending.indexOf(flagUrl), 1)
      // cancelToken不存在，则从队列中删除该请求
    }
  } else {
    // 当前请求不在队列中，就加进队列
    if (f) {
      pending.push(flagUrl)
    }
  }
}

function setConfig (data) {
  if (data) {
    const { signPackage, share, pageName } = data || {}
    pageName && (document.title = pageName)
    Share(signPackage, share)
  }
}

// 请求拦截器
Request.interceptors.request.use(
  config => {
    config.headers.post = Object.assign({}, HEADERS, { Page: getRealHref() }, config.headers)
    config.transformRequest = [data => stringify(data)]
    // 处理重复请求
    config.cancelToken = new CancelToken(c => {
      removePending(config, c)
    })
    return config
  },
  error => {
    Promise.reject(error)
  }
)

Request.interceptors.response.use(
  response => {
    removePending(response.config)
    // res 是 axios 返回数据中的 data
    const res = response.data
    if (!res) {
      createError('服务器内部错误')
    } else {
      const code = res.ret
      switch (code) {
        case 0:
          setConfig(res.config)
          return res.data
        case 1:
          // 后台报错
          createError(res.msg)
          break
        case 2:
          // 后台跳转
          res.url && (window.location.href = res.url)
          break
        case 3:
          // 后台执行js
          /* eslint-disable-next-line */
          res.js && eval(res.js)
          break
        case 102:
          // 用户未登录或登录态过期
          break
        default:
          return res
      }
    }
  },
  error => {
    console.log(error)
    if (error && error.response) {
      const status = error.response.status
      CODE_MESSAGE[status] && (error.message = CODE_MESSAGE[status])
    }
    error.message && Notify(error.message)
    return Promise.reject(error)
  }
)

export default Request
